package me.magicall.test.coll;

import java.io.Serializable;
import java.util.AbstractList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;

import me.magicall.coll.CollFactory;
import me.magicall.coll.ElementTransformer;
import me.magicall.coll.unmodifiable.UnmodifiableListTemplate;

public class MapList<E> extends AbstractList<E> implements List<E>, RandomAccess, Serializable {
	private static final long serialVersionUID = -16787602475127134L;

	private final Map<Integer, E> map;

	public MapList(final int initialCapacity) {
		map = new HashMap<Integer, E>(initialCapacity);
	}

	public MapList() {
		map = new HashMap<Integer, E>();
	}

	@Override
	public E get(final int index) {
		return map.get(index);
	}

	@Override
	public int size() {
		return map.size();
	}

	@Override
	public void add(final int index, final E element) {
		map.put(index, element);
	}

	@Override
	public void clear() {
		map.clear();
	}

	@Override
	public E remove(final int index) {
		return map.remove(index);
	}

	@Override
	protected void removeRange(final int fromIndex, final int toIndex) {
		for (int i = fromIndex; i < toIndex; ++i) {
			remove(i);
		}
	}

	@Override
	public E set(final int index, final E element) {
		return map.put(index, element);
	}

	public static class RepairingHoleList<E> extends UnmodifiableListTemplate<E> {

		private static final long serialVersionUID = 2250704461771153885L;

		private final MapList<E> list;
		private final E defValue;
		private final int size;

		public RepairingHoleList(final Collection<E> source, final int size, final ElementTransformer<E, Integer> elementToIndex, final E defValue) {
			this.size = size;
			this.defValue = defValue;
			list = new MapList<E>(source.size());
			int i = 0;
			for (final E e : source) {
				list.add(elementToIndex.transform(i++, e), e);
			}
		}

		@Override
		protected E get0(final int index) {
			rangeCheck(index);
			final E e = list.get(index);
			return e == null ? defValue : e;
		}

		@Override
		public int size() {
			return size;
		}
	}

	public static void main(final String[] args) {
		final List<Integer> seq = CollFactory.L.seq(1, 2, 10);
		System.out.println("@@@@@@" + seq);
		final RepairingHoleList<Integer> list = new RepairingHoleList<Integer>(seq, 100, new ElementTransformer<Integer, Integer>() {
			@Override
			public Integer transform(final int index, final Integer element) {
				return element;
			}
		}, 0);
		System.out.println("@@@@@@" + list);
		System.out.println("@@@@@@" + list.subList(2, 20));
	}
}
